package cn.com.surker.material.service.impl;

import cn.com.surker.base.system.dao.SysStorageDao;
import cn.com.surker.base.system.dao.SysStorageMatchDao;
import cn.com.surker.base.system.entity.SysStorage;
import cn.com.surker.base.system.entity.SysStorageMatch;
import cn.com.surker.common.MessageCenterException;
import cn.com.surker.database.JDBCTemplateCache;
import cn.com.surker.enums.StateEnum;
import cn.com.surker.enums.base.StorageEnjoyTypeEnum;
import cn.com.surker.enums.material.MaterialInventoryEnum;
import cn.com.surker.enums.system.DataBaseEnum;
import cn.com.surker.material.dao.MainMaterialHistoryInventoryDao;
import cn.com.surker.material.entity.MainMaterialHistoryInventory;
import cn.com.surker.material.service.MaterialHistoryInventoryBaseService;
import cn.com.surker.material.vo.MaterialHistoryInventoryVo;
import cn.com.surker.spring.RestResultDto;
import cn.com.surker.system.dao.DataSourceInfoDao;
import cn.com.surker.system.entity.DataSourceInfo;
import cn.com.surker.util.DateUtil;
import cn.com.surker.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Author lucky
 * @create 2024年11月13 15:39
 * @desc
 */
public abstract class MaterialHistoryInventoryBaseServiceImpl implements MaterialHistoryInventoryBaseService {

    @Resource
    protected MainMaterialHistoryInventoryDao historyInventoryDao;
    @Resource
    protected SysStorageDao sysStorageDao;
    @Resource
    protected SysStorageMatchDao storageMatchDao;
    @Resource
    protected DataSourceInfoDao dsDao;


    /**
     * 校正库存量
     * @param storageId 仓位ID
     * @param initial 期初值kg
     * @param storeValue 校正量kg
     * @param isCloud 0云端 1本地
     * @return
     */
    public RestResultDto updateStoreDosage(Long orgId,Long storageId, Double initial, Double storeValue, String creator, Integer isCloud) {
        if (StringUtils.isAllParamNull(storageId, storeValue))
            throw new MessageCenterException("参数错误");
        if (StringUtils.isNull(isCloud))
            isCloud = 1;
        if (storeValue < 0)
            throw new MessageCenterException("校正库存量不能小于0吨");
        if (isCloud == 1) {
            SysStorage sysStorage = sysStorageDao.selectById(storageId);
            if (sysStorage == null || sysStorage.getStatus().intValue() == 1)
                throw new MessageCenterException("仓位信息不存在或已被禁用");
            List<SysStorageMatch> storageMatchList = storageMatchDao.findByStorageId(storageId);
            if (storageMatchList == null || storageMatchList.size() == 0)
                throw new MessageCenterException("未获取到仓位关联信息");
            Date nowDate = new Date();
            Double adjustment = storeValue - initial;
            String remark = "原材盘点[期初库存:" + (initial / 1000) + "吨调整为最新库存:" + (storeValue / 1000)
                    + "吨,调整值:" + (adjustment / 1000) + "吨]";
            if (sysStorage.getIsEnjoy().intValue() == StorageEnjoyTypeEnum.FGX.getCode()) {
                SysStorageMatch storageMatch = storageMatchList.get(0);
                MainMaterialHistoryInventory historyInventory = new MainMaterialHistoryInventory(storageMatch.getOrgId(),
                        storageMatch.getMaterialId(), storageId, nowDate, nowDate,
                        initial, 0.0, 0.0, adjustment, MaterialInventoryEnum.YCPD.getCode(), storageMatch.getControlId());
                historyInventory.setStatus(0);
                historyInventory.setCreateTime(nowDate);
                historyInventory.setCreator(creator);
                historyInventory.setRemark(remark);
                Integer code = historyInventoryDao.insert(historyInventory);
                if (code > 0)
                    return RestResultDto.success("更新成功", historyInventory);
            } else {
                List<MainMaterialHistoryInventory> tempList = new ArrayList<>();
                for (int i = 0; i < storageMatchList.size(); i++) {
                    SysStorageMatch storageMatch = storageMatchList.get(i);
                    MainMaterialHistoryInventory historyInventory = new MainMaterialHistoryInventory(storageMatch.getOrgId(),
                            storageMatch.getMaterialId(), storageId, nowDate, nowDate,
                            initial, 0.0, 0.0, adjustment, MaterialInventoryEnum.YCPD.getCode(), storageMatch.getControlId());
                    historyInventory.setStatus(0);
                    historyInventory.setCreateTime(nowDate);
                    historyInventory.setCreator(creator);
                    historyInventory.setRemark(remark);
                    tempList.add(historyInventory);
                }
                if (tempList == null || tempList.size() == 0)
                    throw new MessageCenterException("校正盘点仓位数据错误");
                Integer code = historyInventoryDao.saveBatch(tempList);
                if (code > 0)
                    return RestResultDto.success("更新成功");
            }
        } else if (isCloud == 0) {
            DataSourceInfo ds = dsDao.queryDSByOriginIdV1(orgId, DataBaseEnum.MYSQL.getCode());
            String dbCode = ds.getCode();
            SysStorage sysStorage = sysStorageDao.selectCloudById(dbCode, storageId);
            if (sysStorage == null || sysStorage.getStatus().intValue() == 1)
                throw new MessageCenterException("仓位信息不存在或已被禁用");
            List<SysStorageMatch> storageMatchList = storageMatchDao.findByStorageIdV1(dbCode, storageId);
            if (storageMatchList == null || storageMatchList.size() == 0)
                throw new MessageCenterException("未获取到仓位关联信息");
            Date nowDate = new Date();
            Double adjustment = storeValue - initial;
            String remark = "原材盘点[期初库存:" + (initial / 1000) + "吨调整为最新库存:" + (storeValue / 1000)
                    + "吨,调整值:" + (adjustment / 1000) + "吨]";
            JdbcTemplate jdbcTemplate = JDBCTemplateCache.getLocalJdbcTemplate(ds);
            if (sysStorage.getIsEnjoy().intValue() == StorageEnjoyTypeEnum.FGX.getCode()) {
                SysStorageMatch storageMatch = storageMatchList.get(0);
                String nowTime = DateUtil.convertString(nowDate);
                String insertSql = "INSERT INTO main_material_history_inventory (org_id, material_id, store_id, " +
                        "start_date,type, check_date, initial, crease, reduse, adjustment,status, remark, creator, " +
                        "create_time, updator, update_time,control_store_id)\n" +
                        "VALUES (?,?,?,?,?, ?, ?, ?, ?, ?,?, ?, ?, ?, ?, ?,?)";
                Object[] objs = {orgId, storageMatch.getMaterialId(), storageId, nowTime,MaterialInventoryEnum.YCPD.getCode(),
                        nowTime, initial, 0, 0, adjustment,0, remark, creator, nowTime, "", nowTime,storageMatch.getControlId()};

                Integer code = jdbcTemplate.update(insertSql, objs);
                if (code > 0)
                    return RestResultDto.success("库存已更新至ERP本地,请5分钟后刷新查看库存~！");
            } else {
                String nowTime = DateUtil.convertString(nowDate);
                String insertSql = "INSERT INTO main_material_history_inventory (org_id, material_id, store_id, " +
                        "start_date,type, check_date, initial, crease, reduse, adjustment,status, remark, creator, " +
                        "create_time, updator, update_time,control_store_id)\n" +
                        "VALUES (?,?,?,?,?, ?, ?, ?, ?, ?,?, ?, ?, ?, ?, ?,?)";
                List<Object[]> tempList = new ArrayList<>();
                for (int i = 0; i < storageMatchList.size(); i++) {
                    SysStorageMatch storageMatch = storageMatchList.get(i);
                    Object[] objs = {orgId, storageMatch.getMaterialId(), storageId, nowTime,MaterialInventoryEnum.YCPD.getCode(),
                            nowTime, initial, 0, 0, adjustment,0, remark, creator, nowTime, "", nowTime,storageMatch.getControlId()};
                    tempList.add(objs);
                }
                if (tempList == null || tempList.size() == 0)
                    throw new MessageCenterException("校正盘点仓位数据错误");
                jdbcTemplate.update(insertSql, tempList);
                return RestResultDto.success("库存已更新至ERP本地,请5分钟后刷新查看库存~！");
            }
        }

        throw new MessageCenterException("校正盘点仓位数据异常");
    }

    /**
     * 新增历史数据(盘点、工控换材料、定时盘点)
     * @param historyInventory
     * @return
     */
    public RestResultDto saveHistory(MainMaterialHistoryInventory historyInventory) {
        if (historyInventory == null)
            throw new MessageCenterException("参数错误");
        if (StringUtils.isNull(historyInventory.getMaterialId()))
            throw new MessageCenterException("材料信息为空");
        if (StringUtils.isNull(historyInventory.getStoreId()))
            throw new MessageCenterException("仓位信息为空");
        SysStorage storage = sysStorageDao.selectById(historyInventory.getStoreId());
        if (storage == null || storage.getStatus().intValue() == 1)
            throw new MessageCenterException("仓位不存在或已被禁用");
        Date nowDate = new Date();
        if (StringUtils.isNull(historyInventory.getStartDate()))
            historyInventory.setStartDate(nowDate);
        if (StringUtils.isNull(historyInventory.getCheckDate()))
            historyInventory.setCheckDate(nowDate);
        historyInventory.setCreateTime(nowDate);
        Integer code = historyInventoryDao.insert(historyInventory);
        if (code > 0) {
            storage.setInventoryTime(nowDate);
            code = sysStorageDao.updateById(storage);
            if (code > 0)
                return RestResultDto.success("保存成功", historyInventory);
        }
        return RestResultDto.fail("保存失败");
    }

    /**
     * 分页查询盘点信息
     * @param searchVal
     * @param orgId
     * @param materialId
     * @param storageId
     * @param startTime
     * @param endTime
     * @param offset
     * @param limit
     * @return
     */
    public IPage findByPage(String searchVal, Integer type, Long orgId, Long materialId, Long storageId, String startTime,
                     String endTime, Integer offset, Integer limit) {
        QueryWrapper<MainMaterialHistoryInventory> query = initFullParam(searchVal, type, orgId, materialId, storageId, startTime, endTime);
        PageHelper.offsetPage(offset, limit);
        IPage<MainMaterialHistoryInventory> iPage = historyInventoryDao.selectFullPage(new Page<>((offset + limit) /limit, limit), query);
        /**分页插件**/
        if (!StringUtils.isNull(iPage.getRecords())) {
            PageInfo pageInfo = new PageInfo(iPage.getRecords());
            if (!StringUtils.isNull(pageInfo.getTotal()))
                iPage.setTotal(pageInfo.getTotal());
        }
        return iPage;
    }


    /**
     * 根据查询
     * @param controlStorageId
     * @param time
     * @return
     */
    public MaterialHistoryInventoryVo findByControlStorage(Long controlStorageId, String time) {
        if (StringUtils.isAllParamNull(controlStorageId, time))
            throw new MessageCenterException("参数错误");
        MaterialHistoryInventoryVo historyInventoryVo = historyInventoryDao.findByControlMaterial(null, controlStorageId, time);
        return historyInventoryVo;
    }

    /**
     * 超过45天未盘存材料
     * @param orgId
     * @return
     */
    public List<MaterialHistoryInventoryVo> waringInventory(String dbCode, Long orgId) {
        if (StringUtils.isAllParamNull(dbCode, orgId))
            return null;
        Date nowDate = new Date();
        Date startDate = DateUtil.convertBeforeDayDate(nowDate, 45);
        String startTime = DateUtil.convertString(startDate);
        String endTime = DateUtil.convertString(nowDate);
        List<MaterialHistoryInventoryVo> list = historyInventoryDao.findInventoryByOrg(dbCode, orgId, startTime, endTime);
        if (list == null || list.size() == 0)
            return null;
        List<MaterialHistoryInventoryVo> resultList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            MaterialHistoryInventoryVo historyInventoryVo = list.get(i);
            if (historyInventoryVo == null || StringUtils.isNull(historyInventoryVo.getStartDate()))
                continue;
            Integer day = DateUtil.differentDays2(nowDate, historyInventoryVo.getStartDate());
            if (day > 45) {
                historyInventoryVo.setUnInventoryDay(day);
                resultList.add(historyInventoryVo);
            }
        }
        if (resultList == null || resultList.size() == 0)
            return null;
        return resultList;
    }

    protected QueryWrapper<MainMaterialHistoryInventory> initFullParam(String searchVal, Integer type, Long orgId,
                           Long materialId, Long storageId, String startTime, String endTime) {
        QueryWrapper<MainMaterialHistoryInventory> qw = new QueryWrapper<>();
        if (StringUtils.isNotBlank(searchVal)) {
            qw.and(orderWrapper -> orderWrapper.like("a.remark", searchVal).or()
                    .like("c.name", searchVal).like("d.name", searchVal).or()
                    .like("b.name_norms", searchVal));
        }
        if (StringUtils.isNotBlank(startTime)) {
            qw.ge("a.start_date", startTime);
        }
        if (StringUtils.isNotBlank(endTime)) {
            qw.lt("a.start_date", endTime);
        }
        if (type != null) {
            qw.eq("a.type", type);
        }
        if (orgId != null) {
            qw.eq("a.org_id", orgId);
        }
        if (materialId != null) {
            qw.eq("a.material_id", materialId);
        }
        if (storageId != null) {
            qw.eq("a.storage_d", storageId);
        }
        qw.eq("a.status", StateEnum.ENABLED.getCode());
        qw.groupBy("a.id");
        qw.orderByDesc("a.start_date");
        return qw;
    }

}
